package com.yiyuan.app.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.guaike.core.redis.annotation.TryLock;
import com.guaike.core.redis.context.ApiContext;
import com.guaike.core.redis.enums.LockModel;
import com.guaike.core.utils.DateUtil;
import com.yiyuan.app.entity.constant.MQTTTopicConstant;
import com.yiyuan.app.entity.constant.TcpCommandCodeConstant;
import com.yiyuan.app.entity.message.ForbidLookMessage;
import com.yiyuan.app.entity.message.OccupyMessage;
import com.yiyuan.app.entity.result.AppUser;
import com.yiyuan.app.mqtt.MQTTProducer;
import com.yiyuan.app.utils.TcpUtils;
import com.yiyuan.app.dao.*;
import com.yiyuan.app.entity.enums.*;
import com.yiyuan.app.entity.po.*;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.net.Socket;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@AllArgsConstructor
public class BaseUtilService {

    private final UAppUserDAO uAppUserDAO;
    private final UAppUserEquityDAO uAppUserEquityDAO;
    private final MConfPrizeDAO mConfPrizeDAO;
    private final MConfPrizeRuleDAO mConfPrizeRuleDAO;
    private final MRecordSignDetailDAO mRecordSignDetailDAO;
    private final MRecordSeriesRechargeDetailDAO mRecordSeriesRechargeDetailDAO;
    private final MProductSeriesRechargeDaysDAO mProductSeriesRechargeDaysDAO;
    private final MRecordTaskDailyDAO mRecordTaskDailyDAO;
    private final MConfTaskDailyDAO mConfTaskDailyDAO;
    private final MConfTaskDAO mConfTaskDAO;
    private final MRecordTaskDAO mRecordTaskDAO;
    private final MRecordPineDAO mRecordPineDAO;
    private final GRecordGameDAO gRecordGameDAO;
    private final MRecordProductLookDAO mRecordProductLookDAO;
    private final MRecordOccupyDAO mRecordOccupyDAO;
    private final GConfRoomDAO gConfRoomDAO;
    private final GConfRoomDeviceDAO gConfRoomDeviceDAO;
    private final GRecordRoomWatchDAO gRecordRoomWatchDAO;
    private final MQTTProducer messageProducer;
    private final MRankPushCoinsDAO mRankPushCoinsDAO;
    private final GConfDeviceDAO gConfDeviceDAO;

    /**
     * 判断是否新用户签到
     *
     * @return
     */
    public Boolean checkNewSign() {
        AppUser currentUser = ApiContext.getCurrentUser();
        MConfPrizePO prizePO = mConfPrizeDAO.findOne(MConfPrizePO::getAction, PrizeActionEnum.new_sign.getCode());
        if (Objects.isNull(prizePO)) {
            return Boolean.FALSE;
        }
        LocalDate today = LocalDate.now();
        if (PeriodTypeEnum.short_period.getCode().equals(prizePO.getPeriodType())) {
            if (Objects.nonNull(prizePO.getValidDate()) && prizePO.getValidDate().isAfter(today)) {
                return Boolean.FALSE;
            }
            if (Objects.nonNull(prizePO.getExpireDate()) && prizePO.getExpireDate().isBefore(today)) {
                return Boolean.FALSE;
            }
        }
        long count = mConfPrizeRuleDAO.count(new LambdaQueryWrapper<MConfPrizeRulePO>().eq(MConfPrizeRulePO::getPrizeId, prizePO.getId()));
        UAppUserPO userPO = uAppUserDAO.findById(currentUser.getUserId());
        int days = DateUtil.days(userPO.getCreateTime().toLocalDate(), today) + 1;
        if (days > count) {
            return Boolean.FALSE;
        }
        return Boolean.TRUE;
    }

    /**
     * 判断是否用户签到
     *
     * @return
     */
    public Boolean checkSign() {
        MConfPrizePO prizePO = mConfPrizeDAO.findOne(MConfPrizePO::getAction, PrizeActionEnum.sign.getCode());
        if (Objects.isNull(prizePO)) {
            return Boolean.FALSE;
        }
        LocalDate today = LocalDate.now();
        if (PeriodTypeEnum.short_period.getCode().equals(prizePO.getPeriodType())) {
            if (Objects.nonNull(prizePO.getValidDate()) && prizePO.getValidDate().isAfter(today)) {
                return Boolean.FALSE;
            }
            if (Objects.nonNull(prizePO.getExpireDate()) && prizePO.getExpireDate().isBefore(today)) {
                return Boolean.FALSE;
            }
        }
        return Boolean.TRUE;
    }

    /**
     * 判断是否存在邀请奖励
     *
     * @return
     */
    public Boolean checkInvite() {
        MConfPrizePO prizePO = mConfPrizeDAO.findOne(MConfPrizePO::getAction, PrizeActionEnum.invite.getCode());
        if (Objects.isNull(prizePO)) {
            return Boolean.FALSE;
        }
        String formatDate = DateUtil.formatDate(new Date(), "yyyy-MM-dd");
        Date today = DateUtil.parseDate(formatDate, "yyyy-MM-dd");
        if (PeriodTypeEnum.short_period.getCode().equals(prizePO.getPeriodType())) {
            if (Objects.nonNull(prizePO.getValidDate()) && prizePO.getValidDate().isAfter(today.toInstant().atZone(ZoneId.systemDefault()).toLocalDate())) {
                return Boolean.FALSE;
            }
            if (Objects.nonNull(prizePO.getExpireDate()) && prizePO.getExpireDate().isBefore(today.toInstant().atZone(ZoneId.systemDefault()).toLocalDate())) {
                return Boolean.FALSE;
            }
        }
        return Boolean.TRUE;
    }

    /**
     * 判断是否连续签到
     *
     * @return
     */
    public Boolean checkSeriesSign(Long userId, MRecordSignPO recordSignPO, MConfPrizeRulePO rulePO) {
        long count = mConfPrizeRuleDAO.count(new LambdaQueryWrapper<MConfPrizeRulePO>().eq(MConfPrizeRulePO::getPrizeId, rulePO.getPrizeId()));
        if (Objects.isNull(recordSignPO) && rulePO.getSignDay() == 1) {
            return Boolean.TRUE;
        }
        if (Objects.nonNull(recordSignPO)) {
            MRecordSignDetailPO detailPO = mRecordSignDetailDAO.findLatestAlreadySign(userId, recordSignPO.getId());
            if (DateUtil.days(detailPO.getCreateTime().toLocalDate(), LocalDate.now()) == 1
                    && detailPO.getSignDay() + 1 == rulePO.getSignDay() && detailPO.getSignDay() < count) {
                return Boolean.TRUE;
            }
            if (DateUtil.days(detailPO.getCreateTime().toLocalDate(), LocalDate.now()) == 1
                    && detailPO.getSignDay() >= count && rulePO.getSignDay() == 1) {
                return Boolean.TRUE;
            }
            if (DateUtil.days(detailPO.getCreateTime().toLocalDate(), LocalDate.now()) > 1
                    && rulePO.getSignDay() == 1) {
                return Boolean.TRUE;
            }
        }
        return Boolean.FALSE;
    }

    /**
     * 判断是否连续充值
     *
     * @return
     */
    public Boolean checkSeriesRecharge(Long userId, Integer day, MRecordSeriesRechargePO rechargePO) {
        if (Objects.isNull(rechargePO) && day == 1) {
            return Boolean.TRUE;
        }
        if (Objects.nonNull(rechargePO)) {
            MRecordSeriesRechargeDetailPO detailPO = mRecordSeriesRechargeDetailDAO.findLatestAlreadyRecharge(userId, rechargePO.getId());
            if (DateUtil.days(detailPO.getCreateTime().toLocalDate(), LocalDate.now()) == 1
                    && detailPO.getRechargeDay() + 1 == day) {
                return Boolean.TRUE;
            }
            if (DateUtil.days(detailPO.getCreateTime().toLocalDate(), LocalDate.now()) == 1
                    && detailPO.getRechargeDay() == 7 && day == 1) {
                return Boolean.TRUE;
            }
            if (DateUtil.days(detailPO.getCreateTime().toLocalDate(), LocalDate.now()) > 1
                    && day == 1) {
                return Boolean.TRUE;
            }
        }
        return Boolean.FALSE;
    }

    /**
     * 初始化每日任务
     *
     * @param key
     * @param userId
     * @param today
     * @return
     */
    @TryLock(lockKey = "#key", lockModel = LockModel.REENTRANT)
    public Boolean setDailyTask(String key, Long userId, LocalDate today) {
        long count = mRecordTaskDailyDAO.findUserTodayCount(userId, today);
        if (count > 0) {
            return Boolean.TRUE;
        }
        int day = today.getDayOfMonth();
        List<MConfTaskDailyPO> dailyPOS = mConfTaskDailyDAO.findAll(MConfTaskDailyPO::getSortIndex, Boolean.TRUE);
        List<MRecordTaskDailyPO> finalPos = new ArrayList<>();
        dailyPOS.forEach(po -> {
            if (po.getAction().equals(DailyTaskActionEnum.receive.getCode())
                    && po.getPeriod().equals(PeriodEnum.monthly.getCode())) {
                String[] split = po.getPeriodPoint().split(",");
                List<String> list = Arrays.asList(split);
                if (!list.contains(String.valueOf(day))) {
                    return;
                }
            }
            MRecordTaskDailyPO dailyPO = new MRecordTaskDailyPO();
            dailyPO.setUserId(userId);
            dailyPO.setTaskId(po.getId());
            dailyPO.setTaskName(po.getTaskName());
            dailyPO.setAction(po.getAction());
            dailyPO.setIcon(po.getImage());
            dailyPO.setPrize(po.getPinecone());
            dailyPO.setThreshold(po.getThreshold());
            dailyPO.setRecordDate(today);
            dailyPO.setSortIndex(po.getSortIndex());
            if (po.getAction().equals(DailyTaskActionEnum.receive.getCode())) {
                dailyPO.setStatus(TaskStatusEnum.unclaimed.getCode());
            } else {
                dailyPO.setStatus(TaskStatusEnum.go_complete.getCode());
            }
            finalPos.add(dailyPO);
        });
        mRecordTaskDailyDAO.saveBatch(finalPos);
        return Boolean.TRUE;
    }

    @Transactional
    public void dealDailyTaskAllComplete(Long userId, LocalDate today) {
        LambdaQueryWrapper<MRecordTaskDailyPO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MRecordTaskDailyPO::getUserId, userId);
        queryWrapper.eq(MRecordTaskDailyPO::getRecordDate, today);
        queryWrapper.ne(MRecordTaskDailyPO::getAction, DailyTaskActionEnum.all_complete.getCode());
        long allTaskCount = mRecordTaskDailyDAO.count(queryWrapper);
        queryWrapper.ne(MRecordTaskDailyPO::getStatus, TaskStatusEnum.go_complete.getCode());
        long allCompleteTaskCount = mRecordTaskDailyDAO.count(queryWrapper);
        if (allTaskCount == allCompleteTaskCount) {
            LambdaQueryWrapper<MRecordTaskDailyPO> query = new LambdaQueryWrapper<>();
            query.eq(MRecordTaskDailyPO::getUserId, userId);
            query.eq(MRecordTaskDailyPO::getRecordDate, today);
            query.eq(MRecordTaskDailyPO::getAction, DailyTaskActionEnum.all_complete.getCode());
            query.eq(MRecordTaskDailyPO::getStatus, TaskStatusEnum.go_complete.getCode());
            long count = mRecordTaskDailyDAO.count(query);
            if (count > 0) {
                mRecordTaskDailyDAO.updateCompleteTask(userId, today);
            }
        }
    }

    /**
     * 初始化长期任务
     *
     * @param key
     * @param userId
     * @return
     */
    @TryLock(lockKey = "#key", lockModel = LockModel.REENTRANT)
    public Boolean setTask(String key, Long userId) {
        List<MConfTaskPO> taskPOS = mConfTaskDAO.findAll(MConfTaskPO::getSortIndex, Boolean.TRUE);
        List<MRecordTaskPO> recordTaskPOS = mRecordTaskDAO.findList(MRecordTaskPO::getUserId, userId);
        Map<Long, List<MRecordTaskPO>> listMap = recordTaskPOS.stream().collect(Collectors.groupingBy(MRecordTaskPO::getTaskId));
        List<MRecordTaskPO> list = new ArrayList<>();
        List<MRecordTaskPO> updateList = new ArrayList<>();
        taskPOS.forEach(po -> {
            if (CollectionUtils.isEmpty(recordTaskPOS) || CollectionUtils.isEmpty(listMap.get(po.getId()))) {
                MRecordTaskPO recordTaskPO = new MRecordTaskPO();
                recordTaskPO.setUserId(userId);
                recordTaskPO.setTaskId(po.getId());
                recordTaskPO.setTaskName(po.getTaskName());
                recordTaskPO.setAction(po.getAction());
                recordTaskPO.setIcon(po.getImage());
                recordTaskPO.setPrize(po.getPinecone());
                recordTaskPO.setThreshold(po.getThreshold());
                recordTaskPO.setVipLevel(po.getVipLevel());
                recordTaskPO.setStatus(TaskStatusEnum.go_complete.getCode());
                recordTaskPO.setSortIndex(po.getSortIndex());
                list.add(recordTaskPO);
            } else {
                MRecordTaskPO recordTaskPO = listMap.get(po.getId()).get(0);
                if (!po.getSortIndex().equals(recordTaskPO.getSortIndex())) {
                    recordTaskPO.setSortIndex(po.getSortIndex());
                    updateList.add(recordTaskPO);
                }
            }
        });
        if (CollectionUtils.isNotEmpty(list)) {
            mRecordTaskDAO.saveBatch(list);
        }
        if (CollectionUtils.isNotEmpty(updateList)) {
            mRecordTaskDAO.updateBatchById(updateList);
        }
        return Boolean.TRUE;
    }

    public Long getUserPine(Long userId, LocalDate startOfWeek, LocalDate endOfWeek) {
        MRecordPinePO pinePO = mRecordPineDAO.findUserPine(startOfWeek, endOfWeek, userId);
        if (Objects.nonNull(pinePO)) {
            return pinePO.getId();
        }
        pinePO = new MRecordPinePO();
        pinePO.setUserId(userId);
        pinePO.setIsGet(Boolean.FALSE);
        pinePO.setGetPinecone(0);
        pinePO.setStartDate(startOfWeek);
        pinePO.setEndDate(endOfWeek);
        mRecordPineDAO.save(pinePO);
        return pinePO.getId();
    }

    /**
     * 判断是否有人在此房间机位在玩
     *
     * @param key
     * @param userId
     * @param roomId
     * @param positionNo
     * @return
     */
    @TryLock(lockKey = "#key", lockModel = LockModel.REENTRANT)
    @Transactional
    public Long checkGaming(String key, Long userId, Long roomId, String positionNo) {
        GRecordGamePO gamePO = gRecordGameDAO.findRoomPlaying(roomId, positionNo);
        if (Objects.nonNull(gamePO) && !gamePO.getUserId().equals(userId)) {
            return null;
        }
        if (Objects.isNull(gamePO)) {
            LocalDateTime now = LocalDateTime.now();
            GConfRoomPO roomPO = gConfRoomDAO.findById(roomId);
            GConfRoomDevicePO roomDevicePO = gConfRoomDeviceDAO.findOne(roomId, positionNo);
            gamePO = new GRecordGamePO();
            gamePO.setUserId(userId);
            gamePO.setRoomId(roomId);
            gamePO.setPositionNo(positionNo);
            gamePO.setDeviceId(roomDevicePO.getDeviceId());
            MRecordOccupyPO occupyPO = mRecordOccupyDAO.findUserOccupyingOne(userId, roomId, positionNo);
            if (Objects.nonNull(occupyPO)) {
                gamePO.setRecordOccupyId(occupyPO.getId());
            }
            gamePO.setRoomName(roomPO.getRoomName());
            gamePO.setRoomType(roomPO.getRoomType());
            gamePO.setMultipleValue(roomPO.getMultipleValue());
            gamePO.setFinallyCoinTime(now);
            gamePO.setSettleStatus(Boolean.FALSE);
            if (roomPO.getRoomType().equals(RoomTypeEnum.push_coins.getCode())) {
                LocalDateTime end = now.plusSeconds(90L);
                gamePO.setEndTime(end);
            }
            gRecordGameDAO.save(gamePO);
            gRecordRoomWatchDAO.deleteUserWatch(userId, roomId);
        }
        return gamePO.getId();
    }

    /**
     * 判断是否有人在此房间机位在玩
     *
     * @param key
     * @param userId
     * @param roomId
     * @param positionNo
     * @return
     */
    @TryLock(lockKey = "#key", lockModel = LockModel.REENTRANT)
    @Transactional
    public Long startGaming(String key, Long userId, Long roomId, String positionNo) {
        GRecordGamePO gamePO = gRecordGameDAO.findRoomPlaying(roomId, positionNo);
        if (Objects.nonNull(gamePO) && !gamePO.getUserId().equals(userId)) {
            return null;
        }
        if (Objects.isNull(gamePO)) {
            LocalDateTime now = LocalDateTime.now();
            GConfRoomPO roomPO = gConfRoomDAO.findById(roomId);
            GConfRoomDevicePO roomDevicePO = gConfRoomDeviceDAO.findOne(roomId, positionNo);
            gamePO = new GRecordGamePO();
            gamePO.setUserId(userId);
            gamePO.setRoomId(roomId);
            gamePO.setPositionNo(positionNo);
            gamePO.setDeviceId(roomDevicePO.getDeviceId());
            gamePO.setRoomName(roomPO.getRoomName());
            gamePO.setRoomType(roomPO.getRoomType());
            gamePO.setMultipleValue(roomPO.getMultipleValue());
            gamePO.setFinallyCoinTime(now);
            gamePO.setSettleStatus(Boolean.FALSE);
            if (roomPO.getRoomType().equals(RoomTypeEnum.push_coins.getCode())) {
                LocalDateTime end = now.plusSeconds(90L);
                gamePO.setEndTime(end);
            }
            gRecordGameDAO.save(gamePO);
            gRecordRoomWatchDAO.deleteUserWatch(userId, roomId);
        }
        return gamePO.getId();
    }

    @TryLock(lockKey = "#key", lockModel = LockModel.REENTRANT)
    @Transactional
    public Boolean checkGaming(String key, Long userId, Long roomId, String positionNo, Integer type, JSONObject jsonObject) throws IOException, InterruptedException {
        GRecordGamePO gamePO = gRecordGameDAO.findRoomPlaying(roomId, positionNo);
        if (Objects.nonNull(gamePO) && !gamePO.getUserId().equals(userId)) {
            return Boolean.FALSE;
        }
        LocalDateTime now = LocalDateTime.now();
        if (type.equals(OrderProductTypeEnum.lock_machine.getCode())) {
            MRecordProductLookPO lookPO = mRecordProductLookDAO.findUserOne(userId, roomId, positionNo);
            if (Objects.isNull(lookPO)) {
                lookPO = new MRecordProductLookPO();
                lookPO.setUserId(userId);
                lookPO.setRoomId(roomId);
                lookPO.setPositionNo(positionNo);
                lookPO.setProductType(EquityEnum.lock_machine.getCode());
                Integer duration = jsonObject.getInteger("duration");
                LocalDateTime endTime = now.plusMinutes(duration);
                lookPO.setEndTime(endTime);
                mRecordProductLookDAO.save(lookPO);
            } else {
                Integer duration = jsonObject.getInteger("duration");
                LocalDateTime endTime = now.plusMinutes(duration);
                lookPO.setEndTime(endTime);
                mRecordProductLookDAO.updateById(lookPO);
            }
        } else if (type.equals(OrderProductTypeEnum.forbid_look.getCode())) {
            MRecordProductLookPO lookPO = mRecordProductLookDAO.findUserOne(userId, roomId, positionNo);
            if (Objects.isNull(lookPO)) {
                lookPO = new MRecordProductLookPO();
                lookPO.setUserId(userId);
                lookPO.setRoomId(roomId);
                lookPO.setPositionNo(positionNo);
                lookPO.setProductType(EquityEnum.forbid_look.getCode());
                Integer duration = jsonObject.getInteger("duration");
                LocalDateTime endTime = now.plusMinutes(duration);
                lookPO.setEndTime(endTime);
                mRecordProductLookDAO.save(lookPO);
            } else {
                Integer duration = jsonObject.getInteger("duration");
                LocalDateTime endTime = now.plusMinutes(duration);
                lookPO.setEndTime(endTime);
                mRecordProductLookDAO.updateById(lookPO);
            }
            List<GRecordRoomWatchPO> watchPOS = gRecordRoomWatchDAO.findList(GRecordRoomWatchPO::getRoomId, roomId);
            if (CollectionUtils.isNotEmpty(watchPOS)) {
                List<Long> userIds = watchPOS.stream().map(GRecordRoomWatchPO::getUserId).collect(Collectors.toList());
                userIds = userIds.stream().filter(id -> !id.equals(userId)).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(userIds)) {
                    ForbidLookMessage message = new ForbidLookMessage();
                    message.setRoomId(roomId);
                    message.setUserIds(userIds);
                    messageProducer.sendMessage(MQTTTopicConstant.FORBID_LOOK_KEY, JSON.toJSONString(message));
                }
            }
        } else if (type.equals(OrderProductTypeEnum.occupy.getCode())) {
            GConfRoomPO roomPO = gConfRoomDAO.findById(roomId);
            if (Objects.nonNull(gamePO.getRecordOccupyId())) {
                MRecordOccupyPO occupyPO = mRecordOccupyDAO.findById(gamePO.getRecordOccupyId());
                occupyPO.setEndTime(now);
                mRecordOccupyDAO.updateById(occupyPO);
            }
            if (!roomPO.getRoomType().equals(RoomTypeEnum.push_coins.getCode())) {
                settleMachine(gamePO.getDeviceId());
            }
            gRecordGameDAO.updateGameEnd(gamePO.getId());
            Long deviceId = gamePO.getDeviceId();
            MRecordOccupyPO occupyPO = new MRecordOccupyPO();
            occupyPO.setUserId(userId);
            occupyPO.setRoomId(roomId);
            occupyPO.setPositionNo(positionNo);
            Integer duration = jsonObject.getInteger("duration");
            Integer pinecone = jsonObject.getInteger("pinecone");
            occupyPO.setDuration(duration);
            occupyPO.setPinecone(pinecone);
            occupyPO.setStartTime(now);
            occupyPO.setIsSettle(Boolean.FALSE);
            LocalDateTime endTime = now.plusMinutes(duration);
            occupyPO.setEndTime(endTime);
            occupyPO.setCurrentPinecone(pinecone);
            mRecordOccupyDAO.save(occupyPO);
            gamePO = new GRecordGamePO();
            gamePO.setUserId(userId);
            gamePO.setRoomId(roomId);
            gamePO.setDeviceId(deviceId);
            gamePO.setPositionNo(positionNo);
            gamePO.setRecordOccupyId(occupyPO.getId());
            gamePO.setRoomName(roomPO.getRoomName());
            gamePO.setRoomType(roomPO.getRoomType());
            gamePO.setMultipleValue(roomPO.getMultipleValue());
            gamePO.setFinallyCoinTime(now);
            if (roomPO.getRoomType().equals(RoomTypeEnum.push_coins.getCode())) {
                gamePO.setEndTime(endTime);
            }
            gRecordGameDAO.save(gamePO);
            OccupyMessage message = new OccupyMessage();
            message.setRoomId(roomId);
            message.setUserId(userId);
            message.setPositionNo(positionNo);
            message.setDeviceId(deviceId);
            message.setDuration(duration);
            messageProducer.sendMessage(MQTTTopicConstant.ROOM_OCCUPY_KEY, JSON.toJSONString(message));
        }
        return Boolean.TRUE;
    }

    /**
     * 判断是否可以进入房间
     *
     * @param userPO
     * @param equityPO
     * @param roomPO
     * @return
     */
    public Boolean checkIsGoIntoRoom(UAppUserPO userPO, UAppUserEquityPO equityPO, GConfRoomPO roomPO) {
        Boolean flag = Boolean.FALSE;
        Long lock = mRecordProductLookDAO.checkOtherLockEnable(userPO.getId(), roomPO.getId());
        if (lock > 0) {
            return Boolean.FALSE;
        }
        Long occupying = mRecordOccupyDAO.checkOtherUserOccupying(userPO.getId(), roomPO.getId());
        if (occupying > 0) {
            return Boolean.FALSE;
        }
        if (equityPO.getVipGrade() < roomPO.getVipLevel()) {
            if (roomPO.getIsNewArea()) {
                if (userPO.getCreateTime().plusDays(1).compareTo(LocalDateTime.now()) >= 0) {
                    flag = Boolean.TRUE;
                }
            }
        } else {
            flag = Boolean.TRUE;
        }
        return flag;
    }

    @TryLock(lockKey = "#key", lockModel = LockModel.REENTRANT)
    public Long setPushCoinsRank(String key, Long userId, LocalDate startDate, LocalDate endDate) {
        MRankPushCoinsPO pushCoinsPO = mRankPushCoinsDAO.findUserRank(startDate, endDate, userId);
        if (Objects.nonNull(pushCoinsPO)) {
            return pushCoinsPO.getId();
        }
        UAppUserPO userPO = uAppUserDAO.findById(userId);
        UAppUserEquityPO equityPO = uAppUserEquityDAO.findOne(UAppUserEquityPO::getUserId, userId);
        pushCoinsPO = new MRankPushCoinsPO();
        pushCoinsPO.setUserId(userId);
        pushCoinsPO.setNickname(userPO.getNickname());
        pushCoinsPO.setAvatarurl(userPO.getAvatarurl());
        pushCoinsPO.setVipGrade(equityPO.getVipGrade());
        pushCoinsPO.setPushCoinsValue(0);
        pushCoinsPO.setIsRank(Boolean.FALSE);
        pushCoinsPO.setStartDate(startDate);
        pushCoinsPO.setEndDate(endDate);
        mRankPushCoinsDAO.save(pushCoinsPO);
        return pushCoinsPO.getId();
    }

    /**
     * 发送结算街机娱乐
     *
     * @param deviceId
     */
    public void settleMachine(Long deviceId) throws IOException, InterruptedException {
        log.info("开始结算街机");
        GConfDevicePO devicePO = gConfDeviceDAO.findById(deviceId);
        Socket socket = TcpUtils.findSocket(devicePO.getSerialNumber());
        if (Objects.nonNull(socket)) {
            TcpUtils.sendMessage(socket, TcpCommandCodeConstant.STOP);
            Thread.sleep(2000);
            TcpUtils.sendMessage(socket, TcpCommandCodeConstant.SETTLE_APPLY);
        }
    }

    @Transactional
    public void dealSeriesLoginTask(Long userId, Integer days) {
        List<MConfTaskPO> pos = mConfTaskDAO.findList(MConfTaskPO::getAction, TaskActionEnum.login.getCode(), MConfTaskPO::getId, Boolean.TRUE);
        List<MRecordTaskPO> saveList = new ArrayList<>();
        List<MRecordTaskPO> updateList = new ArrayList<>();
        List<Long> ids = pos.stream().map(MConfTaskPO::getId).collect(Collectors.toList());
        List<MRecordTaskPO> recordTaskPOS = mRecordTaskDAO.findListUser(userId, ids);
        Map<Long, List<MRecordTaskPO>> listMap = recordTaskPOS.stream().collect(Collectors.groupingBy(MRecordTaskPO::getTaskId));
        pos.forEach(po -> {
            MRecordTaskPO recordTaskPO = listMap.get(po.getId()).get(0);
            if (Objects.isNull(recordTaskPO)) {
                recordTaskPO = new MRecordTaskPO();
                recordTaskPO.setUserId(userId);
                recordTaskPO.setTaskId(po.getId());
                recordTaskPO.setTaskName(po.getTaskName());
                recordTaskPO.setAction(po.getAction());
                recordTaskPO.setIcon(po.getImage());
                recordTaskPO.setPrize(po.getPinecone());
                recordTaskPO.setThreshold(po.getThreshold());
                recordTaskPO.setVipLevel(po.getVipLevel());
                recordTaskPO.setCurrentProgress(days);
                recordTaskPO.setStatus(TaskStatusEnum.go_complete.getCode());
                if (days >= po.getThreshold()) {
                    recordTaskPO.setStatus(TaskStatusEnum.unclaimed.getCode());
                }
                saveList.add(recordTaskPO);
            } else {
                if (days >= po.getThreshold() && recordTaskPO.getStatus().equals(TaskStatusEnum.go_complete.getCode())) {
                    recordTaskPO.setCurrentProgress(days);
                    recordTaskPO.setStatus(TaskStatusEnum.unclaimed.getCode());
                    updateList.add(recordTaskPO);
                }
            }
        });
        if (CollectionUtils.isNotEmpty(saveList)) {
            mRecordTaskDAO.saveBatch(saveList);
        }
        if (CollectionUtils.isNotEmpty(updateList)) {
            mRecordTaskDAO.updateBatchById(updateList);
        }
    }
}
